package com.example.config;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;


@Component
@Slf4j
public class RabbitMQInitializer {

    @Autowired
    private AmqpAdmin amqpAdmin;

    @Value("${order.main.exchange}")
    private String mainExchange;

    @Value("${order.main.queue}")
    private String mainMqQueue;

    @Value("${order.main.routingKey}")
    private String mainMqRoutingKey;

    @PostConstruct
    public void init() {
        //不绑定死信队列的版本
        // 声明Direct类型Exchange
        DirectExchange orderExchange = new DirectExchange("order.exchange", true, false);
        amqpAdmin.declareExchange(orderExchange);

        // 声明持久化队列（队列名称、持久化、独占、自动删除）
        Queue orderQueue = new Queue("order.queue", true, false, false);
        amqpAdmin.declareQueue(orderQueue);

        // 绑定Exchange与Queue（Binding Key为"order.create"）
        Binding binding = BindingBuilder.bind(orderQueue)
                .to(orderExchange)
                .with("order.create");
        amqpAdmin.declareBinding(binding);


        //--------------------------------------------------------------------------------------------------------------
        // 声明Direct类型Exchange
        DirectExchange orderTryExchange = new DirectExchange("order.try.exchange", true, false);
        amqpAdmin.declareExchange(orderTryExchange);

        // 声明持久化队列（队列名称、持久化、独占、自动删除）
        Queue orderTryQueue = new Queue("order.try.queue", true, false, false);
        amqpAdmin.declareQueue(orderTryQueue);

        // 绑定Exchange与Queue（Binding Key为"order.create"）
        Binding tryBinding = BindingBuilder.bind(orderTryQueue)
                .to(orderTryExchange)
                .with("order.try.create");
        amqpAdmin.declareBinding(tryBinding);



        //----------------------------------------------------------------------------------------------------
        //绑定死信队列的版本,设置指定次数


        // 声明死信Exchange
        DirectExchange dlxExchange = new DirectExchange("order.dlx.exchange", true, false);
        amqpAdmin.declareExchange(dlxExchange);

        // 声明死信队列
        Queue dlq = new Queue("order.dlx.queue", true, false, false);
        amqpAdmin.declareQueue(dlq);

        // 绑定死信队列
        Binding dlqBinding = BindingBuilder.bind(dlq)
                .to(dlxExchange)
                .with("order.dlx");
        amqpAdmin.declareBinding(dlqBinding);

        // 声明主队列并设置DLX参数
        Map<String, Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange", "order.dlx.exchange");  // DLX Exchange名称
        args.put("x-dead-letter-routing-key", "order.dlx");       // DLX Routing Key
        args.put("x-max-retries",8);                               // 最大重试次数（需配合插件）
        Queue mainQueue = new Queue(mainMqQueue, true, false, false, args);
        amqpAdmin.declareQueue(mainQueue);
        // 声明Direct类型Exchange
        DirectExchange orderMainExchange = new DirectExchange(mainExchange, true, false);
        amqpAdmin.declareExchange(orderMainExchange);
        // 绑定主队列到主Exchange
        Binding mainBinding = BindingBuilder.bind(mainQueue)
                .to(orderMainExchange)
                .with(mainMqRoutingKey);
        amqpAdmin.declareBinding(mainBinding);



        //----------------------------------------------------------------------------------------------------
        //绑定死信队列的版本，设置超时时间，自动的acknowledge-mode: AUTO会进入死信队列，手动ack的只能重启进入


        // 声明死信Exchange
        DirectExchange dlx1Exchange = new DirectExchange("order.dlx1.exchange", true, false);
        amqpAdmin.declareExchange(dlx1Exchange);

        // 声明死信队列
        Queue dlq1 = new Queue("order.dlx1.queue", true, false, false);
        amqpAdmin.declareQueue(dlq1);

        // 绑定死信队列
        Binding dlq1Binding = BindingBuilder.bind(dlq1)
                .to(dlx1Exchange)
                .with("order.dlx1");
        amqpAdmin.declareBinding(dlq1Binding);

        // 声明主队列并设置DLX参数
        Map<String, Object> args1 = new HashMap<>();
        args1.put("x-dead-letter-exchange", "order.dlx1.exchange");  // DLX Exchange名称
        args1.put("x-dead-letter-routing-key", "order.dlx1");       // DLX Routing Key
        args1.put("x-message-ttl", 60000);                              // 设置队列中消息的TTL为60秒（60000毫秒）

        Queue main1Queue = new Queue("order.main1.queue", true, false, false, args1);
        amqpAdmin.declareQueue(main1Queue);
        // 声明Direct类型Exchange
        DirectExchange orderMain1Exchange = new DirectExchange("order.main1.exchange", true, false);
        amqpAdmin.declareExchange(orderMain1Exchange);
        // 绑定主队列到主Exchange
        Binding main1Binding = BindingBuilder.bind(main1Queue)
                .to(orderMain1Exchange)
                .with("order.main1.create");
        amqpAdmin.declareBinding(main1Binding);


        //------------------------------------------------------------------------------------------------
        // 声明延迟队列  RabbitMQ插件方案（rabbitmq-delayed-message-exchange）
        Queue delayQueue = new Queue("order.delay.queue", true, false, false);
        amqpAdmin.declareQueue(delayQueue);

        // 声明延迟交换机
        // 声明延迟交换机（x-delayed-message 类型）
        Map<String, Object> exchangeArgs = new HashMap<>();
        exchangeArgs.put("x-delayed-type", "topic");
        CustomExchange delayExchange = new CustomExchange("order.delay.exchange", "x-delayed-message",true,false, exchangeArgs);
        amqpAdmin.declareExchange(delayExchange);
        // 绑定延迟队列到延迟交换机
        BindingBuilder.GenericArgumentsConfigurer with = BindingBuilder.bind(delayQueue).to(delayExchange).with("order.delay");
        amqpAdmin.declareBinding(with.noargs());


        //------------------------------------------------------------------------------------------------
        // 延迟队列  RabbitMQ原生方案 TTL + 死信队列方案
// 声明延迟队列（主队列）的DLX为实际消费队列
        Map<String, Object> delayArgs = new HashMap<>();
        // 设置队列中消息的TTL（毫秒）
//        delayArgs.put("x-message-ttl", 60000);
        // 设置死信交换机
        delayArgs.put("x-dead-letter-exchange", "order.dlx.exchange");   // 实际消费的Exchange
        // 设置死信路由键
        delayArgs.put("x-dead-letter-routing-key", "order.dlx"); // 实际消费的Routing Key
        Queue delayQueueTtl = new Queue("order.delay1.queue", true, false, false, delayArgs);
        amqpAdmin.declareQueue(delayQueueTtl);
        // 声明Direct类型Exchange
        DirectExchange orderDelay1Exchange = new DirectExchange("order.delay1.exchange", true, false);
        amqpAdmin.declareExchange(orderDelay1Exchange);
        // 绑定主队列到主Exchange
        Binding delay1Binding = BindingBuilder.bind(delayQueueTtl)
                .to(orderDelay1Exchange)
                .with("order.delay1");
        amqpAdmin.declareBinding(delay1Binding);





        //------------------------------------------------------------------------------------------------
        //优先级设置
        // 声明优先级队列，这里重点是concurrency=1，prefetch=1，保证每次只处理一个消息
        Map<String, Object> priority = new HashMap<>();
        priority.put("x-max-priority", 10); // 设置最大优先级为10
        Queue priorityQueue = new Queue("order.priority.queue", true, false, false, priority);
        amqpAdmin.declareQueue(priorityQueue);

        // 声明交换机
        DirectExchange priorityExchange = new DirectExchange("order.priority.exchange", true, false);
        amqpAdmin.declareExchange(priorityExchange);

        // 绑定队列和交换机
        Binding priorityBinding = BindingBuilder.bind(priorityQueue)
                .to(priorityExchange)
                .with("order.priority");
        amqpAdmin.declareBinding(priorityBinding);

        //---------------------------------------------------------------------------------------------


        //设置批量发送和消费的队列
        Queue batchQueue = new Queue("order.batch.queue", true, false, false);
        amqpAdmin.declareQueue(batchQueue);
        // 声明交换机
        DirectExchange batchExchange = new DirectExchange("order.batch.exchange", true, false);
        amqpAdmin.declareExchange(batchExchange);

        // 绑定队列和交换机
        Binding batchBinding = BindingBuilder.bind(batchQueue)
                .to(batchExchange)
                .with("order.batch");
        amqpAdmin.declareBinding(batchBinding);



        //-------------------------------------------------------------------------------------------------------
        //异步发送

        Queue asyncQueue = new Queue("order.async.queue", true, false, false);
        amqpAdmin.declareQueue(asyncQueue);
        // 声明交换机
        DirectExchange asyncExchange = new DirectExchange("order.async.exchange", true, false);
        amqpAdmin.declareExchange(asyncExchange);

        // 绑定队列和交换机
        Binding asyncBinding = BindingBuilder.bind(asyncQueue)
                .to(asyncExchange)
                .with("order.async");
        amqpAdmin.declareBinding(asyncBinding);

        //-------------------------------------------------------------------------------------------------------
        //发送顺序消息sequence
        Queue sequenceQueue = new Queue("order.sequence.queue", true, false, false);
        amqpAdmin.declareQueue(sequenceQueue);
        // 声明交换机
        DirectExchange sequenceExchange = new DirectExchange("order.sequence.exchange", true, false);
        amqpAdmin.declareExchange(sequenceExchange);

        // 绑定队列和交换机
        Binding sequenceBinding = BindingBuilder.bind(sequenceQueue)
                .to(sequenceExchange)
                .with("order.sequence");
        amqpAdmin.declareBinding(sequenceBinding);

    }

    @Bean
    public String mainQueueName() {
        return mainMqQueue;
    }
}